﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.OracleClient;
using GotDotNet.ApplicationBlocks.Data;
using System.IO;
using System.Diagnostics;
using NUnit.Framework;
using System.Xml;
using System.Threading;
namespace DataTrans
{
    
    public partial class Form1 : Form
    {
        
        public Form1()
        {
            InitializeComponent();
        }

        private string nodename = "";

        private void InitDropDownList()
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load("config.xml");

            XmlNodeList xnl = xmlDoc.SelectSingleNode("config").ChildNodes;

            foreach (XmlNode xn in xnl)//遍历所有子节点
            {
                XmlElement xe = (XmlElement)xn;
                this.comboBox1.Items.Add(xe.GetAttribute("name"));
            }
            if (this.comboBox1.Items.Count > 0)
                this.comboBox1.SelectedItem = this.comboBox1.Items[0];
            
        }

        private ConfigNode ReadXml(string node2)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load("config.xml");

            XmlNode xnl = xmlDoc.SelectSingleNode("config/add[@name='" + node2 + "']");
            XmlElement xe = (XmlElement)xnl;
            this.tbColumnName.Text = xe.GetAttribute("blobColumnName");
            this.tbTableName.Text = xe.GetAttribute("TableName");
            this.tbPkname.Text = xe.GetAttribute("primaryKey");
            this.tbUrlName.Text = xe.GetAttribute("UrlWriteBackColumnName");
            this.tbFileName.Text = xe.GetAttribute("filename");
            this.tbSmallColumnName.Text = xe.GetAttribute("SmallUrlWriteBackColumnName");
            ConfigNode node = new ConfigNode();
            node.blobColumnName = xe.GetAttribute("blobColumnName");
            node.TableName = xe.GetAttribute("TableName");
            node.primaryKey = xe.GetAttribute("primaryKey");
            node.UrlWriteBackColumnName = xe.GetAttribute("UrlWriteBackColumnName");
            node.filename = xe.GetAttribute("filename");
            node.SmallUrlWriteBackColumnName = xe.GetAttribute("SmallUrlWriteBackColumnName");
            node.width = xe.GetAttribute("width");
            node.width = xe.GetAttribute("height");
            node.folder = this.tbFolderName.Text;
            node.connstring = this.tbConnstring.Text;

            return node;
        }

        #region DoChangePhoto

        private void DoChangePhoto()
        {
            ConfigNode cn = this.ReadXml(this.nodename);

            string s_connstring = cn.connstring;
            //string s_connstring2 = this.conn2.Text;
            string s_cnt_sql = "select count(1) from " + this.tbTableName.Text;
            string s_select_sql = "select " + cn.primaryKey + " as pk," + cn.filename + "," +
                cn.blobColumnName + " from " + cn.TableName;// +" where rownum<100";
            AdoHelper helper = AdoHelper.CreateHelper("GotDotNet.ApplicationBlocks.Data", System.Configuration.ConfigurationManager.AppSettings["DBType"].ToString());
            OracleConnection ic = null;
            OracleDataReader rdr = null;
            int cnt = int.Parse(helper.ExecuteScalar(s_connstring, CommandType.Text, s_cnt_sql).ToString());
            string pkID = "";
            try
            {
                //IDataParameter p = helper.GetParameter();
                //p.DbType = DbType.Binary;
                //p.ParameterName = this.tbColumnName.Text;
                ic = new OracleConnection(s_connstring);//helper.GetConnection(s_connstring);

                ic.Open();
                OracleCommand command = ic.CreateCommand();
                command.CommandType = CommandType.Text;
                command.CommandText = s_select_sql;
                rdr = command.ExecuteReader(CommandBehavior.SequentialAccess);
                // Writes the BLOB to a file (*.bmp).
                FileStream stream;
                // Streams the BLOB to the FileStream object.
                BinaryWriter writer;

                // Size of the BLOB buffer.
                int bufferSize = 100;
                // The BLOB byte[] buffer to be filled by GetBytes.
                byte[] outByte = new byte[bufferSize];
                // The bytes returned from GetBytes.
                long retval;
                // The starting position in the BLOB output.
                long startIndex = 0;
                int i = 0;
                ShowProgressDelegate showProgress = new ShowProgressDelegate(OnProgress);
                while (rdr.Read())
                {
                    i++;
                    if (this.progressBar1.InvokeRequired)
                    {
                        this.BeginInvoke(showProgress, new object[] { i * 100 / cnt });
                    }
                    
                    pkID = rdr.GetString(0);
                    string file_ext = rdr.GetString(1);
                    string s_filename = "pic" + Guid.NewGuid().ToString() + this.GetFileExt(file_ext);
                    string s_path = cn.folder + "\\large\\" + s_filename;
                    using (stream = new FileStream(s_path, FileMode.OpenOrCreate, FileAccess.Write))
                    {
                        //stream = new FileStream(s_path, FileMode.OpenOrCreate, FileAccess.Write);
                        writer = new BinaryWriter(stream);

                        // Reset the starting byte for the new BLOB.
                        startIndex = 0;

                        // Read bytes into outByte[] and retain the number of bytes returned.
                        retval = rdr.GetBytes(2, startIndex, outByte, 0, bufferSize);

                        // Continue while there are bytes beyond the size of the buffer.
                        while (retval == bufferSize)
                        {
                            writer.Write(outByte);
                            writer.Flush();

                            // Reposition start index to end of last buffer and fill buffer.
                            startIndex += bufferSize;
                            retval = rdr.GetBytes(2, startIndex, outByte, 0, bufferSize);
                        }

                        // Write the remaining buffer.
                        if (retval > 0)
                            writer.Write(outByte, 0, (int)retval - 1);
                        writer.Flush();

                        // Close the output file.
                        writer.Close();
                        stream.Close();
                    }


                    //回写路径
                    //AdoHelper helper2 = AdoHelper.CreateHelper("GotDotNet.ApplicationBlocks.Data", System.Configuration.ConfigurationManager.AppSettings["DBType2"].ToString());

                    string sql = "update " + this.tbTableName.Text + " set " + this.tbUrlName.Text + "='" + s_filename + "' where " + this.tbPkname.Text + "='" + pkID + "'";
                    helper.ExecuteNonQuery(s_connstring, CommandType.Text, sql);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "pkid=" + pkID);
                return;
            }
            finally
            {
                if (rdr != null && !rdr.IsClosed)
                    rdr.Close();
                if (ic.State == ConnectionState.Closed)
                    ic.Close();
            }
        }
        #endregion

        private void btnStart_Click(object sender, EventArgs e)
        {
            this.nodename = this.comboBox1.SelectedItem.ToString();
            this.progressBar1.Maximum = 100;
            this.progressBar1.Minimum = 0;
            this.progressBar1.Value = 0;
            //this.DoChangePhoto();

            ThreadStart ts = new ThreadStart(this.DoChangePhoto);
            Thread t = new Thread(ts);
            t.Start();
        }

        #region MakeThumbnail

        public void MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height, string mode)
        {

            Image originalImage =
                Image.FromFile(originalImagePath);
            int towidth = width;
            int toheight = height;
        
            int x = 0;
            int y = 0;
            int ow = originalImage.Width;
            int oh = originalImage.Height;        

            switch (mode)
            {        
                case "HW"://指定高宽缩放（可能变形）                
                    break;
                case "W"://指定宽，高按比例                    
                    toheight = originalImage.Height * width/originalImage.Width;
                    break;
                case "H"://指定高，宽按比例
                    towidth = originalImage.Width * height/originalImage.Height;                    
                    break;        
                case "Cut"://指定高宽裁减（不变形）                
                    if((double)originalImage.Width/(double)originalImage.Height > (double)towidth/(double)toheight)
                    {
                        oh = originalImage.Height;
                        ow = originalImage.Height*towidth/toheight;
                        y = 0;
                        x = (originalImage.Width - ow)/2;
                    }
                    else
                    {
                        ow = originalImage.Width;
                        oh = originalImage.Width*height/towidth;
                        x = 0;
                        y = (originalImage.Height - oh)/2;
                    }
                    break;                    
                    default :
                    break;
            }    
            
            //新建一个bmp图片
            Image bitmap = new System.Drawing.Bitmap(towidth,toheight);

            //新建一个画板
            Graphics g = System.Drawing.Graphics.FromImage(bitmap);

            //设置高质量插值法
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

            //设置高质量,低速度呈现平滑程度
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            //清空画布并以透明背景色填充
            g.Clear(Color.Transparent);        

            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight), 
                new Rectangle(x, y, ow,oh),
                GraphicsUnit.Pixel);

            try
            {
                //以jpg格式保存缩略图
                bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            catch (System.Exception e)
            {
                throw e;
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }
        }
        #endregion

        private void Form1_Load(object sender, EventArgs e)
        {
            this.tbConnstring.Text = System.Configuration.ConfigurationManager.ConnectionStrings["Connstring"].ToString();
            //this.conn2.Text = System.Configuration.ConfigurationManager.ConnectionStrings["Connstring2"].ToString();
            InitDropDownList();

            this.showProgress = new ShowProgressDelegate(OnProgress);
        }

        private void btnSelectFolder_Click(object sender, EventArgs e)
        {
            if (this.folderBrowserDialog1.ShowDialog()==DialogResult.OK)
            {
                this.tbFolderName.Text = this.folderBrowserDialog1.SelectedPath;
            }
        }

        private string GetFileExt(string filename)
        {
            int s = filename.LastIndexOfAny(new char[] { '.' });
            if(s<0)
                return ".jpg";
            string a = filename.Substring(s);
            return a;
        }
        [Test]
        public void TestFileExt()
        {
            string filename = @".jpg";
            int s = filename.LastIndexOfAny(new char[] { '.' });
            string a = filename.Substring(s);
            Debug.Assert(a == ".jpg");
            Debug.Print(a);

        }
        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.ReadXml(this.comboBox1.SelectedItem.ToString());
        }

        private void OnProgress(int i)
        {
            if (this.progressBar1.InvokeRequired)
            {
                this.BeginInvoke(showProgress, new object[] { i });
            }
            else
            {
                this.progressBar1.Value = i;
                this.lblProgress.Text = "已处理" + i.ToString() + "%...";
            }
        }

        delegate void ShowProgressDelegate(int totalStep);
        ShowProgressDelegate showProgress;

        private void Go()
        {
            for (int i = 0; i < 100; i++)
            {
                System.Threading.Thread.Sleep(100);
                OnProgress(i * 100 / 1000);
            }
        }

        private void GetAllThumbnail()
        {
            string target_dir = this.tbFolderName.Text + "\\small\\";
            string source_dir = this.tbFolderName.Text + "\\large\\";
            ShowProgressDelegate showProgress = new ShowProgressDelegate(OnProgress);
            DirectoryInfo UnPostil = new DirectoryInfo(source_dir);
            FileInfo[] ArrUnPostil = UnPostil.GetFiles();
            
            int i = 0;
            foreach (FileInfo f in ArrUnPostil)
            {
                i++;
                try
                {
                    this.MakeThumbnail(f.FullName, target_dir + f.Name, 200, 150, "HW");
                }
                catch { }

                /*if (this.progressBar1.InvokeRequired)
                {
                    this.BeginInvoke(showProgress, new object[] { i*100/ArrUnPostil.Length });
                }*/
                showProgress(i * 100 / ArrUnPostil.Length);
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            this.progressBar1.Maximum = 100;
            this.progressBar1.Minimum = 0;
            this.progressBar1.Value = 0;
            ThreadStart ts = new ThreadStart(GetAllThumbnail);
            Thread t = new Thread(ts);
            t.Start();
        }
    }


    public class ConfigNode
    {
        public string name;
        public string TableName;
        public string blobColumnName;
        public string primaryKey;
        public string UrlWriteBackColumnName;
        public string SmallUrlWriteBackColumnName;
        public string filename;
        public string width;
        public string height;
        public string folder;
        public string connstring;

    }

}